package com.harmony.pilot.analysis.service.impl;

import com.harmony.pilot.common.constants.ServiceConstants;
import com.harmony.pilot.common.dto.*;
import com.harmony.pilot.analysis.service.AnalysisService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.web.reactive.function.client.WebClient;

import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

/**
 * 代码分析服务实现
 */
@Slf4j
@Service
public class AnalysisServiceImpl implements AnalysisService {
    
    private final WebClient dataClient;
    private final WebClient llmClient;
    
    @Value("${analysis.enable-codeql}")
    private Boolean enableCodeQL;
    
    @Value("${analysis.enable-llm}")
    private Boolean enableLLM;
    
    @Value("${analysis.max-issues}")
    private Integer maxIssues;
    
    public AnalysisServiceImpl(@Value("${service.data.url}") String dataUrl,
                                @Value("${service.llm.url}") String llmUrl) {
        this.dataClient = WebClient.builder().baseUrl(dataUrl).build();
        this.llmClient = WebClient.builder().baseUrl(llmUrl).build();
    }
    
    @Override
    public AnalysisResult analyzeCode(AnalysisRequest request) {
        log.info("Analyzing code: {}", request.getContext().getFilePath());
        
        List<AnalysisResult.Issue> allIssues = new ArrayList<>();
        
        // 1. 语法检查
        if (shouldCheck(request, ServiceConstants.ANALYSIS_SYNTAX)) {
            allIssues.addAll(performSyntaxCheck(request));
        }
        
        // 2. 代码风格检查
        if (shouldCheck(request, ServiceConstants.ANALYSIS_STYLE)) {
            allIssues.addAll(performStyleCheck(request));
        }
        
        // 3. 安全检查
        if (shouldCheck(request, ServiceConstants.ANALYSIS_SECURITY)) {
            allIssues.addAll(performSecurityCheck(request));
        }
        
        // 4. 性能检查
        if (shouldCheck(request, ServiceConstants.ANALYSIS_PERFORMANCE)) {
            allIssues.addAll(performPerformanceCheck(request));
        }
        
        // 5. 使用CodeQL检查
        if (enableCodeQL && request.getUseCodeQL()) {
            allIssues.addAll(performCodeQLCheck(request));
        }
        
        // 6. 使用LLM增强分析
        if (enableLLM) {
            allIssues.addAll(performLLMCheck(request));
        }
        
        // 过滤和排序
        List<AnalysisResult.Issue> filteredIssues = filterAndSortIssues(allIssues, request);
        
        // 计算评分
        int score = calculateScore(filteredIssues);
        
        // 生成摘要
        String summary = generateSummary(filteredIssues);
        
        return AnalysisResult.builder()
                .issues(filteredIssues)
                .score(score)
                .summary(summary)
                .build();
    }
    
    @Override
    public AnalysisResult checkSyntax(AnalysisRequest request) {
        List<AnalysisResult.Issue> issues = performSyntaxCheck(request);
        return buildResult(issues);
    }
    
    @Override
    public AnalysisResult checkStyle(AnalysisRequest request) {
        List<AnalysisResult.Issue> issues = performStyleCheck(request);
        return buildResult(issues);
    }
    
    @Override
    public AnalysisResult checkSecurity(AnalysisRequest request) {
        List<AnalysisResult.Issue> issues = performSecurityCheck(request);
        return buildResult(issues);
    }
    
    @Override
    public AnalysisResult checkPerformance(AnalysisRequest request) {
        List<AnalysisResult.Issue> issues = performPerformanceCheck(request);
        return buildResult(issues);
    }
    
    /**
     * 执行语法检查
     */
    private List<AnalysisResult.Issue> performSyntaxCheck(AnalysisRequest request) {
        List<AnalysisResult.Issue> issues = new ArrayList<>();
        
        CodeContext context = request.getContext();
        String code = context.getCode();
        
        // 简单的语法检查规则
        if (code != null) {
            // 检查括号匹配
            if (!checkBracketMatching(code)) {
                issues.add(createIssue(
                    "syntax-001",
                    ServiceConstants.ANALYSIS_SYNTAX,
                    ServiceConstants.SEVERITY_ERROR,
                    "Mismatched brackets or braces",
                    context.getFilePath(),
                    "Check bracket pairing",
                    "static"
                ));
            }
            
            // 检查分号
            if (code.trim().endsWith("{") && !code.contains(";")) {
                issues.add(createIssue(
                    "syntax-002",
                    ServiceConstants.ANALYSIS_SYNTAX,
                    ServiceConstants.SEVERITY_WARNING,
                    "Missing semicolon",
                    context.getFilePath(),
                    "Add semicolon at the end of statement",
                    "static"
                ));
            }
        }
        
        return issues;
    }
    
    /**
     * 执行代码风格检查
     */
    private List<AnalysisResult.Issue> performStyleCheck(AnalysisRequest request) {
        List<AnalysisResult.Issue> issues = new ArrayList<>();
        
        CodeContext context = request.getContext();
        String code = context.getCode();
        
        if (code != null) {
            // 检查命名规范
            if (code.matches(".*class\\s+[a-z].*")) {
                issues.add(createIssue(
                    "style-001",
                    ServiceConstants.ANALYSIS_STYLE,
                    ServiceConstants.SEVERITY_WARNING,
                    "Class name should start with uppercase letter",
                    context.getFilePath(),
                    "Use PascalCase for class names",
                    "static"
                ));
            }
            
            // 检查缩进（简化检查）
            String[] lines = code.split("\n");
            for (int i = 0; i < lines.length; i++) {
                if (lines[i].startsWith("\t")) {
                    issues.add(createIssue(
                        "style-002",
                        ServiceConstants.ANALYSIS_STYLE,
                        ServiceConstants.SEVERITY_INFO,
                        "Use spaces instead of tabs for indentation",
                        context.getFilePath(),
                        "Replace tabs with spaces",
                        "static"
                    ));
                    break;
                }
            }
        }
        
        return issues;
    }
    
    /**
     * 执行安全检查
     */
    private List<AnalysisResult.Issue> performSecurityCheck(AnalysisRequest request) {
        List<AnalysisResult.Issue> issues = new ArrayList<>();
        
        CodeContext context = request.getContext();
        String code = context.getCode();
        
        if (code != null) {
            // 检查不安全的函数
            if (code.contains("strcpy(") || code.contains("sprintf(")) {
                issues.add(createIssue(
                    "security-001",
                    ServiceConstants.ANALYSIS_SECURITY,
                    ServiceConstants.SEVERITY_ERROR,
                    "Use of unsafe function (strcpy/sprintf)",
                    context.getFilePath(),
                    "Use safer alternatives like strncpy or snprintf",
                    "static"
                ));
            }
            
            // 检查内存泄漏风险
            if (code.contains("new ") && !code.contains("delete ") && !code.contains("unique_ptr")) {
                issues.add(createIssue(
                    "security-002",
                    ServiceConstants.ANALYSIS_SECURITY,
                    ServiceConstants.SEVERITY_WARNING,
                    "Potential memory leak - new without delete",
                    context.getFilePath(),
                    "Consider using smart pointers (unique_ptr, shared_ptr)",
                    "static"
                ));
            }
        }
        
        return issues;
    }
    
    /**
     * 执行性能检查
     */
    private List<AnalysisResult.Issue> performPerformanceCheck(AnalysisRequest request) {
        List<AnalysisResult.Issue> issues = new ArrayList<>();
        
        CodeContext context = request.getContext();
        String code = context.getCode();
        
        if (code != null) {
            // 检查低效的循环
            if (code.matches(".*for\\s*\\(.*size\\(\\).*")) {
                issues.add(createIssue(
                    "performance-001",
                    ServiceConstants.ANALYSIS_PERFORMANCE,
                    ServiceConstants.SEVERITY_INFO,
                    "Calling size() in loop condition may be inefficient",
                    context.getFilePath(),
                    "Cache size() result before the loop",
                    "static"
                ));
            }
            
            // 检查不必要的拷贝
            if (code.matches(".*for\\s*\\(\\s*\\w+\\s+\\w+\\s*:.*")) {
                issues.add(createIssue(
                    "performance-002",
                    ServiceConstants.ANALYSIS_PERFORMANCE,
                    ServiceConstants.SEVERITY_WARNING,
                    "Range-based for loop may cause unnecessary copies",
                    context.getFilePath(),
                    "Use const reference: for (const auto& item : container)",
                    "static"
                ));
            }
        }
        
        return issues;
    }
    
    /**
     * 使用CodeQL检查
     */
    private List<AnalysisResult.Issue> performCodeQLCheck(AnalysisRequest request) {
        try {
            // 调用数据服务的CodeQL接口
            List<AnalysisResult.Issue> issues = dataClient.post()
                    .uri("/data/codeql/analyze")
                    .bodyValue(request.getContext())
                    .retrieve()
                    .bodyToFlux(AnalysisResult.Issue.class)
                    .collectList()
                    .block();
            
            return issues != null ? issues : new ArrayList<>();
        } catch (Exception e) {
            log.warn("Failed to perform CodeQL check", e);
            return new ArrayList<>();
        }
    }
    
    /**
     * 使用LLM增强检查
     */
    private List<AnalysisResult.Issue> performLLMCheck(AnalysisRequest request) {
        try {
            String prompt = buildLLMPrompt(request);
            
            LLMRequest llmRequest = LLMRequest.builder()
                    .prompt(prompt)
                    .systemPrompt("You are a C++ code analyzer. Identify potential issues.")
                    .temperature(0.3)
                    .maxTokens(1000)
                    .build();
            
            List<AnalysisResult.Issue> issues = llmClient.post()
                    .uri("/llm/analyze")
                    .bodyValue(llmRequest)
                    .retrieve()
                    .bodyToFlux(AnalysisResult.Issue.class)
                    .collectList()
                    .block();
            
            return issues != null ? issues : new ArrayList<>();
        } catch (Exception e) {
            log.warn("Failed to perform LLM check", e);
            return new ArrayList<>();
        }
    }
    
    /**
     * 检查是否应该执行某种类型的检查
     */
    private boolean shouldCheck(AnalysisRequest request, String type) {
        List<String> types = request.getAnalysisTypes();
        return types == null || types.isEmpty() || types.contains(type);
    }
    
    /**
     * 过滤和排序问题
     */
    private List<AnalysisResult.Issue> filterAndSortIssues(
            List<AnalysisResult.Issue> issues, AnalysisRequest request) {
        
        String severityLevel = request.getSeverityLevel();
        
        return issues.stream()
                .filter(issue -> shouldIncludeIssue(issue, severityLevel))
                .sorted((a, b) -> {
                    // 按严重级别排序：error > warning > info > hint
                    int priorityA = getSeverityPriority(a.getSeverity());
                    int priorityB = getSeverityPriority(b.getSeverity());
                    return Integer.compare(priorityB, priorityA);
                })
                .limit(maxIssues)
                .collect(Collectors.toList());
    }
    
    /**
     * 判断是否应该包含某个问题
     */
    private boolean shouldIncludeIssue(AnalysisResult.Issue issue, String severityLevel) {
        int issuePriority = getSeverityPriority(issue.getSeverity());
        int filterPriority = getSeverityPriority(severityLevel);
        return issuePriority >= filterPriority;
    }
    
    /**
     * 获取严重级别优先级
     */
    private int getSeverityPriority(String severity) {
        return switch (severity) {
            case ServiceConstants.SEVERITY_ERROR -> 4;
            case ServiceConstants.SEVERITY_WARNING -> 3;
            case ServiceConstants.SEVERITY_INFO -> 2;
            case ServiceConstants.SEVERITY_HINT -> 1;
            default -> 0;
        };
    }
    
    /**
     * 计算代码评分
     */
    private int calculateScore(List<AnalysisResult.Issue> issues) {
        int baseScore = 100;
        int deduction = 0;
        
        for (AnalysisResult.Issue issue : issues) {
            switch (issue.getSeverity()) {
                case ServiceConstants.SEVERITY_ERROR -> deduction += 10;
                case ServiceConstants.SEVERITY_WARNING -> deduction += 5;
                case ServiceConstants.SEVERITY_INFO -> deduction += 2;
                case ServiceConstants.SEVERITY_HINT -> deduction += 1;
            }
        }
        
        return Math.max(0, baseScore - deduction);
    }
    
    /**
     * 生成分析摘要
     */
    private String generateSummary(List<AnalysisResult.Issue> issues) {
        long errors = issues.stream()
                .filter(i -> ServiceConstants.SEVERITY_ERROR.equals(i.getSeverity()))
                .count();
        long warnings = issues.stream()
                .filter(i -> ServiceConstants.SEVERITY_WARNING.equals(i.getSeverity()))
                .count();
        long infos = issues.stream()
                .filter(i -> ServiceConstants.SEVERITY_INFO.equals(i.getSeverity()))
                .count();
        
        return String.format("Found %d issue(s): %d error(s), %d warning(s), %d info(s)",
                issues.size(), errors, warnings, infos);
    }
    
    /**
     * 构建分析结果
     */
    private AnalysisResult buildResult(List<AnalysisResult.Issue> issues) {
        return AnalysisResult.builder()
                .issues(issues)
                .score(calculateScore(issues))
                .summary(generateSummary(issues))
                .build();
    }
    
    /**
     * 创建问题对象
     */
    private AnalysisResult.Issue createIssue(String id, String type, String severity,
                                              String message, String filePath,
                                              String fixSuggestion, String source) {
        return AnalysisResult.Issue.builder()
                .id(id)
                .type(type)
                .severity(severity)
                .message(message)
                .filePath(filePath)
                .fixSuggestion(fixSuggestion)
                .source(source)
                .build();
    }
    
    /**
     * 检查括号匹配
     */
    private boolean checkBracketMatching(String code) {
        int parentheses = 0;
        int braces = 0;
        int brackets = 0;
        
        for (char c : code.toCharArray()) {
            switch (c) {
                case '(' -> parentheses++;
                case ')' -> parentheses--;
                case '{' -> braces++;
                case '}' -> braces--;
                case '[' -> brackets++;
                case ']' -> brackets--;
            }
        }
        
        return parentheses == 0 && braces == 0 && brackets == 0;
    }
    
    /**
     * 构建LLM提示词
     */
    private String buildLLMPrompt(AnalysisRequest request) {
        CodeContext context = request.getContext();
        StringBuilder sb = new StringBuilder();
        
        sb.append("Analyze the following C++ code and identify potential issues:\n\n");
        sb.append("File: ").append(context.getFilePath()).append("\n\n");
        sb.append("Code:\n").append(context.getCode()).append("\n\n");
        sb.append("Focus on: syntax, style, security, and performance issues.");
        
        return sb.toString();
    }
}

